#region License
// Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)
/*
 * This license governs use of the accompanying software. If you use the software, you
 * accept this license. If you do not accept the license, do not use the software.
 * 
 * 1. Definitions
 * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
 * same meaning here as under U.S. copyright law.
 * A "contribution" is the original software, or any additions or changes to the software.
 * A "contributor" is any person that distributes its contribution under this license.
 * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
 * 
 * 2. Grant of Rights
 * (A) Copyright Grant- Subject to the terms of this license, including the license conditions 
 *     and limitations in section 3, each contributor grants you a non-exclusive, worldwide, 
 *     royalty-free copyright license to reproduce its contribution, prepare derivative works 
 *     of its contribution, and distribute its contribution or any derivative works that you create.
 * (B) Patent Grant- Subject to the terms of this license, including the license conditions and 
 *     limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free 
 *     license under its licensed patents to make, have made, use, sell, offer for sale, import, 
 *     and/or otherwise dispose of its contribution in the software or derivative works of the 
 *     contribution in the software.
 * 
 * 3. Conditions and Limitations
 * (A) No Trademark License- This license does not grant you rights to use any contributors' 
 *     name, logo, or trademarks.
 * (B) If you bring a patent claim against any contributor over patents that you claim are 
 *     infringed by the software, your patent license from such contributor to the software 
 *     ends automatically.
 * (C) If you distribute any portion of the software, you must retain all copyright, patent, 
 *     trademark, and attribution notices that are present in the software.
 * (D) If you distribute any portion of the software in source code form, you may do so only under 
 *     this license by including a complete copy of this license with your distribution. If you 
 *     distribute any portion of the software in compiled or object code form, you may only do so 
 *     under a license that complies with this license.
 * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no 
 *     express warranties, guarantees or conditions. You may have additional consumer rights under 
 *     your local laws which this license cannot change. To the extent permitted under your local laws, 
 *     the contributors exclude the implied warranties of merchantability, fitness for a particular 
 *     purpose and non-infringement.
 * 
 */
#endregion

using System;
using NPack.Interfaces;

namespace NPack
{
    /// <summary>
    /// A matrix component or matrix element which represents a 
    /// <see cref="System.Double"/>.
    /// </summary>
    /// <remarks>
    /// Use this structure as the type parameter for <see cref="IMatrix{T}"/> when you want
    /// a matrix of Double values, since it implements <see cref="IComputable{T}"/>, which 
    /// allows numerical operations on value types.
    /// </remarks>
    [Serializable]
    public struct DoubleComponent : IEquatable<DoubleComponent>,
                                    IComparable<DoubleComponent>,
                                    IComputable<Double, DoubleComponent>,
                                    IEquatable<Double>,
                                    IComparable<Double>,
                                    IComputable<Double>,
                                    IConvertible,
                                    IFormattable
    {
        private Double _value;

        ///<summary>
        /// Creates a new <see cref="DoubleComponent"/> converting from the given <paramref name="value"/>.
        ///</summary>
        ///<param name="value">The Double used to set the DoubleComponent value.</param>
        public DoubleComponent(Double value)
        {
            _value = value;
        }

        /// <summary>
        /// Returns String representation of this value.
        /// </summary>
        /// <returns>A formatted String displaying this value.</returns>
        public override String ToString()
        {
            return _value.ToString();
        }

        /// <summary>
        /// Generates a hash code for the DoubleComponent value.
        /// </summary>
        /// <returns>A value to represent this value in a hash table.</returns>
        public override Int32 GetHashCode()
        {
            return _value.GetHashCode();
        }

        /// <summary>
        /// Implicitly converts a Double value to a DoubleComponent.
        /// </summary>
        /// <param name="value">Value to convert.</param>
        /// <returns>
        /// A DoubleComponent set to <paramref name="value"/>.
        /// </returns>
        public static implicit operator DoubleComponent(Double value)
        {
            return new DoubleComponent(value);
        }

        /// <summary>
        /// Explicitly converts a DoubleComponent to a Double.
        /// </summary>
        /// <param name="component">DoubleComponent to convert.</param>
        /// <returns>
        /// Value of type Double with the same value as the DoubleComponent.
        /// </returns>
        public static explicit operator Double(DoubleComponent component)
        {
            return component._value;
        }

        /// <summary>
        /// Adds a DoubleComponent and a Double.
        /// </summary>
        /// <param name="lhs">Left hand of the addition operation.</param>
        /// <param name="rhs">Right hand of the addition operation.</param>
        /// <returns>
        /// The sum of <paramref name="lhs"/> and <paramref name="rhs"/>.
        /// </returns>
        public static Double operator +(DoubleComponent lhs, Double rhs)
        {
            return lhs._value + rhs;
        }

        /// <summary>
        /// Subtracts a Double from a DoubleComponent.
        /// </summary>
        /// <param name="lhs">Left hand of the subtraction operation.</param>
        /// <param name="rhs">Right hand of the subtraction operation.</param>
        /// <returns>
        /// The difference of <paramref name="lhs"/> and <paramref name="rhs"/>.
        /// </returns>
        public static Double operator -(DoubleComponent lhs, Double rhs)
        {
            return lhs._value - rhs;
        }

        #region IEquatable<DoubleComponent> Members

        /// <summary>
        /// Evaluates equality of two DoubleComponent instances.
        /// </summary>
        /// <param name="other">The DoubleComponent to compare to.</param>
        /// <returns>
        /// True if the two DoubleComponent instances are equal; false otherwise.
        /// </returns>
        public Boolean Equals(DoubleComponent other)
        {
            return _value == other._value;
        }

        #endregion

        #region IComparable<DoubleComponent> Members

        /// <summary>
        /// Compares two DoubleComponent instances.
        /// </summary>
        /// <param name="other">The DoubleComponent to compare to.</param>
        /// <returns>
        /// 0 if they are equal,
        /// 1 if the called-on instance is greater, 
        /// -1 if <paramref name="other"/> is greater.
        /// </returns>
        public Int32 CompareTo(DoubleComponent other)
        {
            return _value.CompareTo(other._value);
        }

        #endregion

        #region IAddable<DoubleComponent> Members

        /// <summary>
        /// Adds two DoubleComponent values.
        /// </summary>
        /// <param name="a">The other addend.</param>
        /// <returns>
        /// The sum of this DoubleComponent and <paramref name="a"/>.
        /// </returns>
        public DoubleComponent Add(DoubleComponent a)
        {
            return new DoubleComponent(_value + a._value);
        }

        #endregion

        #region ISubtractable<DoubleComponent> Members

        /// <summary>
        /// Subtracts two DoubleComponent values.
        /// </summary>
        /// <param name="a">The subtrahend.</param>
        /// <returns>
        /// The difference of this DoubleComponent (minuend) and 
        /// <paramref name="a"/>.
        /// </returns>
        public DoubleComponent Subtract(DoubleComponent a)
        {
            return new DoubleComponent(_value - a._value);
        }

        #endregion

        #region IHasZero<DoubleComponent> Members

        /// <summary>
        /// Returns the zero value for a DoubleComponent. Equal to 0F.
        /// </summary>
        public DoubleComponent Zero
        {
            get { return new DoubleComponent(0); }
        }

        #endregion

        #region INegatable<DoubleComponent> Members

        /// <summary>
        /// Returns the negation of the DoubleComponent value. Also the
        /// additive inverse.
        /// </summary>
        /// <remarks>
        /// The value returns solves the following equation:
        /// <code>
        /// DoubleComponent a = 5, b = a.Negative();
        /// 
        /// Assert.IsTrue(a.Add(b).Equals(0));
        /// </code>
        /// </remarks>
        /// <returns>The negated DoubleComponent.</returns>
        public DoubleComponent Negative()
        {
            return new DoubleComponent(-_value);
        }

        #endregion

        #region IMultipliable<DoubleComponent> Members

        /// <summary>
        /// Multiplies two DoubleComponents and returns the product.
        /// </summary>
        /// <param name="a">The multiplier.</param>
        /// <returns>
        /// The product of the DoubleComponent instance and 
        /// <paramref name="a"/>.
        /// </returns>
        public DoubleComponent Multiply(DoubleComponent a)
        {
            return new DoubleComponent(_value * a._value);
        }

        #endregion

        #region IDivisible<DoubleComponent> Members

        /// <summary>
        /// Divides two DoubleComponent instances and returns the quotient.
        /// </summary>
        /// <param name="a">The divisor.</param>
        /// <returns>
        /// The quotient of dividing the DoubleComponent instance
        /// (the dividend) and <paramref name="a"/>.
        /// </returns>
        public DoubleComponent Divide(DoubleComponent a)
        {
            return new DoubleComponent(_value / a._value);
        }

        #endregion

        #region IHasOne<DoubleComponent> Members

        /// <summary>
        /// Returns the multiplicative identity.
        /// </summary>
        public DoubleComponent One
        {
            get { return new DoubleComponent(1); }
        }

        #endregion

        #region IEquatable<Double> Members

        /// <summary>
        /// Evaluates equality of a DoubleComponent instance and a Double value.
        /// </summary>
        /// <param name="other">The Double value to compare to.</param>
        /// <returns>
        /// True if the two DoubleComponent instances are equal; false otherwise.
        /// </returns>
        public Boolean Equals(Double other)
        {
            return _value == other;
        }

        #endregion

        #region IComparable<Double> Members

        /// <summary>
        /// Compares a DoubleComponent instance and a Double value.
        /// </summary>
        /// <param name="other">The Double value to compare to.</param>
        /// <returns>
        /// 0 if they are equal,
        /// 1 if the DoubleComponent instance is greater, 
        /// -1 if <paramref name="other"/> is greater.
        /// </returns>
        public Int32 CompareTo(Double other)
        {
            return _value.CompareTo(other);
        }

        #endregion

        #region IAddable<Double> Members

        /// <summary>
        /// Adds a DoubleComponent value and a Double.
        /// </summary>
        /// <param name="a">The other addend.</param>
        /// <returns>
        /// The sum of this DoubleComponent and <paramref name="a"/>.
        /// </returns>
        Double IAddable<Double>.Add(Double a)
        {
            return _value + a;
        }

        #endregion

        #region ISubtractable<Double> Members

        /// <summary>
        /// Subtracts a Double value from the DoubleComponent value.
        /// </summary>
        /// <param name="a">The subtrahend.</param>
        /// <returns>
        /// The difference of this DoubleComponent (minuend) and 
        /// <paramref name="a"/>.
        /// </returns>
        Double ISubtractable<Double>.Subtract(Double a)
        {
            return _value - a;
        }

        #endregion

        #region IHasZero<Double> Members

        /// <summary>
        /// Gets the additive identity as a Double: 0F.
        /// </summary>
        Double IHasZero<Double>.Zero
        {
            get { return 0.0; }
        }

        #endregion

        #region INegatable<Double> Members

        /// <summary>
        /// Returns the negation of the DoubleComponent value as a Double. Also the
        /// additive inverse.
        /// </summary>
        /// <remarks>
        /// The value returns solves the following equation:
        /// <code>
        /// DoubleComponent a = 5, b = a.Negative();
        /// 
        /// Assert.IsTrue(a.Add(b).Equals(0));
        /// </code>
        /// </remarks>
        /// <returns>The negated DoubleComponent as a Double.</returns>
        Double INegatable<Double>.Negative()
        {
            return -_value;
        }

        #endregion

        #region IMultipliable<Double> Members

        /// <summary>
        /// Multiplies the DoubleComponent with Double and returns the product.
        /// </summary>
        /// <param name="a">The multiplier.</param>
        /// <returns>
        /// The product of the DoubleComponent instance and 
        /// <paramref name="a"/>.
        /// </returns>
        Double IMultipliable<Double>.Multiply(Double a)
        {
            return _value * a;
        }

        #endregion

        #region IDivisible<Double> Members

        /// <summary>
        /// Divides the DoubleComponent by a Double and returns the quotient.
        /// </summary>
        /// <param name="a">The divisor.</param>
        /// <returns>
        /// The quotient of dividing the DoubleComponent instance
        /// (the dividend) and <paramref name="a"/>.
        /// </returns>
        Double IDivisible<Double>.Divide(Double a)
        {
            return _value / a;
        }

        #endregion

        #region IHasOne<Double> Members

        /// <summary>
        /// Gets the multiplicative identity as a Double: 1F.
        /// </summary>
        Double IHasOne<Double>.One
        {
            get { return 1.0; }
        }

        #endregion

        #region IBooleanComparable<DoubleComponent> Members

        /// <summary>
        /// Evaluates if the DoubleComponent instance is greater than 
        /// the given value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>True if the DoubleComponent instance is greater
        /// than <paramref name="value"/>; false otherwise.</returns>
        public Boolean GreaterThan(DoubleComponent value)
        {
            return _value > value._value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is greater than 
        /// or equal to the given value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>
        /// True if the DoubleComponent instance is greater
        /// than or equal to <paramref name="value"/>; false otherwise.
        /// </returns>
        public Boolean GreaterThanOrEqualTo(DoubleComponent value)
        {
            return _value >= value._value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is less than 
        /// the given value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>True if the DoubleComponent instance is less
        /// than <paramref name="value"/>; false otherwise.</returns>
        public Boolean LessThan(DoubleComponent value)
        {
            return _value < value._value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is less than 
        /// or equal to the given value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>
        /// True if the DoubleComponent instance is less
        /// than or equal to <paramref name="value"/>; false otherwise.
        /// </returns>
        public Boolean LessThanOrEqualTo(DoubleComponent value)
        {
            return _value <= value._value;
        }

        #endregion

        #region IBooleanComparable<Double> Members

        /// <summary>
        /// Evaluates if the DoubleComponent instance is greater than 
        /// the given Double value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>True if the DoubleComponent instance is greater
        /// than <paramref name="value"/>; false otherwise.</returns>
        public Boolean GreaterThan(Double value)
        {
            return _value > value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is greater than 
        /// or equal to the given Double value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>
        /// True if the DoubleComponent instance is greater
        /// than or equal to <paramref name="value"/>; false otherwise.
        /// </returns>
        public Boolean GreaterThanOrEqualTo(Double value)
        {
            return _value >= value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is less than 
        /// the given Double value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>True if the DoubleComponent instance is less
        /// than <paramref name="value"/>; false otherwise.</returns>
        public Boolean LessThan(Double value)
        {
            return _value < value;
        }

        /// <summary>
        /// Evaluates if the DoubleComponent instance is less than 
        /// or equal to the given Double value.
        /// </summary>
        /// <param name="value">The value to compare to.</param>
        /// <returns>
        /// True if the DoubleComponent instance is less
        /// than or equal to <paramref name="value"/>; false otherwise.
        /// </returns>
        public Boolean LessThanOrEqualTo(Double value)
        {
            return _value <= value;
        }

        #endregion

        #region IExponential<DoubleComponent> Members

        /// <summary>
        /// Raises the DoubleComponent value to the given exponent.
        /// <paramref name="power"/>.
        /// </summary>
        /// <param name="power">
        /// The value of the exponent.
        /// </param>
        /// <returns>
        /// The value of the DoubleComponent (the base) 
        /// raised to the given power.
        /// </returns>
        public DoubleComponent Power(Double power)
        {
            return new DoubleComponent(Math.Pow(_value, power));
        }

        /// <summary>
        /// Computes the value of the square root of the DoubleComponent.
        /// </summary>
        /// <returns>
        /// The value of the square root of the DoubleComponent.
        /// </returns>
        public DoubleComponent Sqrt()
        {
            return new DoubleComponent(Math.Sqrt(_value));
        }

        /// <summary>
        /// Computes the log of the DoubleComponent in the
        /// <paramref name="newBase">given base</paramref>.
        /// </summary>
        /// <param name="newBase">The base to compute the log in.</param>
        /// <returns>
        /// The log of the DoubleComponent in the new base given.
        /// </returns>
        public DoubleComponent Log(Double newBase)
        {
            return new DoubleComponent(Math.Log(_value, newBase));
        }

        /// <summary>
        /// Computes the log of the DoubleComponent in base e.
        /// </summary>
        /// <returns>The natural log of the DoubleComponent.</returns>
        public DoubleComponent Log()
        {
            return new DoubleComponent(Math.Log(_value));
        }

        /// <summary>
        /// Computes e to the power of the DoubleComponent.
        /// </summary>
        /// <returns>
        /// The natural log base, e, raised to the power 
        /// of the value of the DoubleComponent.
        /// </returns>
        public DoubleComponent Exp()
        {
            return new DoubleComponent(Math.Exp(_value));
        }

        #endregion

        #region IExponential<Double> Members

        /// <summary>
        /// Raises the DoubleComponent value to the given 
        /// exponent, returned as a Double.
        /// <paramref name="power"/>.
        /// </summary>
        /// <param name="power">
        /// The value of the exponent.
        /// </param>
        /// <returns>
        /// The value of the DoubleComponent (the base) 
        /// raised to the given power.
        /// </returns>
        Double IExponential<Double>.Power(Double power)
        {
            return Math.Pow(_value, power);
        }

        /// <summary>
        /// Computes the value of the square root of the DoubleComponent,
        /// returned as a Double.
        /// </summary>
        /// <returns>
        /// The value of the square root of the DoubleComponent.
        /// </returns>
        Double IExponential<Double>.Sqrt()
        {
            return Math.Sqrt(_value);
        }

        Double IExponential<Double>.Log(Double newBase)
        {
            return Math.Log(_value, newBase);
        }

        /// <summary>
        /// Computes the log of the DoubleComponent in base 10,
        /// returned as a Double.
        /// </summary>
        /// <returns>
        /// The log of the DoubleComponent in the new base given.
        /// </returns>
        Double IExponential<Double>.Log()
        {
            return Math.Log(_value);
        }

        /// <summary>
        /// Computes the log of the DoubleComponent in base e,
        /// returned as a Double.
        /// </summary>
        /// <returns>The natural log of the DoubleComponent.</returns>
        Double IExponential<Double>.Exp()
        {
            return Math.Exp(_value);
        }

        #endregion

        #region IComputable<DoubleComponent> Members

        /// <summary>
        /// Computes the absolute value of the DoubleComponent.
        /// </summary>
        /// <returns>
        /// The absolute value of the DoubleComponent's value.
        /// </returns>
        public DoubleComponent Abs()
        {
            return new DoubleComponent(Math.Abs(_value));
        }

        /// <summary>
        /// Sets the value of the DoubleComponent.
        /// </summary>
        /// <param name="value">
        /// The value to set the DoubleComponent to, cast to a Double.
        /// </param>
        /// <returns>
        /// A DoubleComponent with the given <paramref name="value"/>.
        /// </returns>
        public DoubleComponent Set(Double value)
        {
            _value = value;
            return this;
        }

        #endregion

        #region IComputable<Double> Members

        /// <summary>
        /// Computes the absolute value of the DoubleComponent,
        /// returned as a Double.
        /// </summary>
        /// <returns>
        /// The absolute value of the DoubleComponent's value.
        /// </returns>
        Double IComputable<Double>.Abs()
        {
            return Math.Abs(_value);
        }

        /// <summary>
        /// Computes the absolute value of the DoubleComponent,
        /// returned as a Double.
        /// </summary>
        /// <returns>
        /// The absolute value of the DoubleComponent's value.
        /// </returns>
        Double IComputable<Double>.Set(Double value)
        {
            _value = value;
            return _value;
        }

        #endregion

        #region IConvertible Members

        /// <summary>
        /// Gets the TypeCode value for the DoubleComponent.
        /// </summary>
        /// <returns><see cref="TypeCode.Double"/></returns>
        public TypeCode GetTypeCode()
        {
            return TypeCode.Double;
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Boolean"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Boolean"/>.</returns>
        public Boolean ToBoolean(IFormatProvider provider)
        {
            return Convert.ToBoolean(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Byte"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Byte"/>.</returns>
        public Byte ToByte(IFormatProvider provider)
        {
            return Convert.ToByte(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Char"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Char"/>.</returns>
        public Char ToChar(IFormatProvider provider)
        {
            return Convert.ToChar(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="DateTime"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="DateTime"/>.</returns>
        public DateTime ToDateTime(IFormatProvider provider)
        {
            return Convert.ToDateTime(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Decimal"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Decimal"/>.</returns>
        public Decimal ToDecimal(IFormatProvider provider)
        {
            return Convert.ToDecimal(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Double"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Double"/>.</returns>
        public Double ToDouble(IFormatProvider provider)
        {
            return _value;
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Int16"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Int16"/>.</returns>
        public Int16 ToInt16(IFormatProvider provider)
        {
            return Convert.ToInt16(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Int32"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Int32"/>.</returns>
        public Int32 ToInt32(IFormatProvider provider)
        {
            return Convert.ToInt32(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Int64"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Int64"/>.</returns>
        public Int64 ToInt64(IFormatProvider provider)
        {
            return Convert.ToInt64(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="SByte"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="SByte"/>.</returns>
        [CLSCompliant(false)]
        public SByte ToSByte(IFormatProvider provider)
        {
            return Convert.ToSByte(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="Single"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="Single"/>.</returns>
        public Single ToSingle(IFormatProvider provider)
        {
            return Convert.ToSingle(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="String"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="String"/>.</returns>
        public String ToString(IFormatProvider provider)
        {
            return Convert.ToString(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a value of the given type.
        /// </summary>
        /// <param name="conversionType">
        /// Type to convert to.
        /// </param>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>
        /// The DoubleComponent as a value of <paramref name="conversionType"/>.
        /// </returns>
        public Object ToType(Type conversionType, IFormatProvider provider)
        {
            return Convert.ChangeType(_value, conversionType, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="UInt16"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="UInt16"/>.</returns>
        [CLSCompliant(false)]
        public UInt16 ToUInt16(IFormatProvider provider)
        {
            return Convert.ToUInt16(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="UInt32"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="UInt32"/>.</returns>
        [CLSCompliant(false)]
        public UInt32 ToUInt32(IFormatProvider provider)
        {
            return Convert.ToUInt32(_value, provider);
        }

        /// <summary>
        /// Converts the DoubleComponent to a <see cref="UInt64"/> value.
        /// </summary>
        /// <param name="provider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help convert the DoubleComponent value.
        /// </param>
        /// <returns>The DoubleComponent as a <see cref="UInt64"/>.</returns>
        [CLSCompliant(false)]
        public UInt64 ToUInt64(IFormatProvider provider)
        {
            return Convert.ToUInt64(_value, provider);
        }

        #endregion

        #region IFormattable Members

        /// <summary>
        /// Generates a String representation of the DoubleComponent.
        /// </summary>
        /// <param name="format">The format String to use in formatting.</param>
        /// <param name="formatProvider">
        /// An <see cref="IFormatProvider"/> instance used to 
        /// help format the DoubleComponent value.
        /// </param>
        /// <returns>
        /// A formatted String which represents the DoubleComponent value.
        /// </returns>
        public String ToString(String format, IFormatProvider formatProvider)
        {
            return _value.ToString(format, formatProvider);
        }

        #endregion

        /// <summary>
        /// Returns the sum of the Object and <paramref name="b"/>.
        /// It must not modify the value of the Object.
        /// </summary>
        /// <param name="b">The second operand.</param>
        /// <returns>The sum.</returns>
        public DoubleComponent Add(Double b)
        {
            return new DoubleComponent(_value + b);
        }

        /// <summary>
        /// Returns the quotient of the Object and <paramref name="b"/>.
        /// It must not modify the value of the Object.
        /// </summary>
        /// <param name="b">The second operand.</param>
        /// <returns>The quotient.</returns>
        public DoubleComponent Divide(Double b)
        {
            return new DoubleComponent(_value / b);
        }

        /// <summary>
        /// Returns the product of the Object and <paramref name="b"/>.
        /// It must not modify the value of the Object.
        /// </summary>
        /// <param name="b">The factor to multiply by.</param>
        /// <returns>The product.</returns>
        public DoubleComponent Multiply(Double b)
        {
            return new DoubleComponent(_value * b);
        }

        /// <summary>
        /// Returns the difference of the Object and <paramref name="b"/>.
        /// It must not modify the value of the Object.
        /// </summary>
        /// <param name="b">The second operand.</param>
        /// <returns>The difference.</returns>
        public DoubleComponent Subtract(Double b)
        {
            return new DoubleComponent(_value - b);
        }
    }
}